package shark.picture.utils.aes;


import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class AesUtils {
    private static String key = "truesharemanyous";
    private static String iv = "showbeingarebyme";

	/**
	 * 小程序版本
	 */
	private static String miniKey = "BraisedPorkChops";
    private static String miniIv = "MacaroonCupcakes";

    /**
     * 终端转发
     */
    private static String terminalKey = "wwwdxinforcomkey";
    private static String terminalIv = "comdxinforwwwniv";

    /**
     * 营销任务管理
     */
    private static String keyYx = "xiatianzenmeguoa";
    private static String ivYx = "pijiushaokaoxlxa";

    /**
     * 公网转发
     */
    private static String tmlKey = "wwwdxinforcomkey";
    private static String tmlIv = "comdxinforwwwniv";

    /**
     * 年度账单
     */
    private static String annualEbillKey = "annualebillbillb";
    private static String annualEbillIv = "alipaywechatpayp";

    /**
     * 解密
     *
     * @return
     * @throws Exception
     */
    public static String desEncrypt(String data) throws Exception {
        if (StringUtils.isNotEmpty(data) && !"null".equals(data)) {
            //data = URLDecoder.decode(data,"UTF-8");
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "UTF-8");
            return originalString.trim();
        } else {
            return null;
        }

    }


    /**
     * 加密
     *
     * @return
     * @throws Exception
     */
    public static String encrypt(String data) throws Exception {
        if (StringUtils.isNotEmpty(data)) {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes("UTF-8");
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new BASE64Encoder().encode(encrypted);
        } else {
            return null;
        }
    }

    /**
     * 加密
     *
     * @return
     * @throws Exception
     */
    public static String encrypt2(String data) throws Exception {
        if (StringUtils.isNotEmpty(data)) {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes("UTF-8");
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new BASE64Encoder().encode(encrypted);
        } else {
            return null;
        }
    }

    public static String encryptForTemplate(String data) throws Exception {
        if (StringUtils.isNotEmpty(data)) {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes("UTF-8");
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new BASE64Encoder().encode(encrypted).replace("+", "@").replace("/", "$").replace("=", "*");
        } else {
            return null;
        }
    }

    public static String desEncryptForTemplate(String data) throws Exception {
        data = data.replace("@", "+").replace("$", "/").replace("*", "=");
        if (StringUtils.isNotEmpty(data) && !"null".equals(data)) {
            //data = URLDecoder.decode(data,"UTF-8");
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "UTF-8");
            return originalString.trim();
        } else {
            return null;
        }

    }

	/**
	 * 加密  转换后不含特殊字符
	 *
	 * @param value
	 * @return
	 */
	public static String encryptMINI(String value) {
		if (StringUtils.isNotEmpty(value)) {
			try {
				Cipher cipher = initCipherMINI(Cipher.ENCRYPT_MODE);
				byte[] bytes = getBytes(cipher, value);
				String encode = new BASE64Encoder().encode(bytes);
				String str = encode.replaceAll("\\+", "-").replaceAll("/", "_");
				return str.replaceAll("\\r|\\n", "").replaceAll("=", "");
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return "";
	}

    /**
     * 解密
     *
     * @param value
     * @return
     */
    public static String decryptMINI(String value) {
        if (!StringUtils.isEmpty(value)) {
            try {
                while ((value.length()) % 4 != 0) {
                    value += "=";
                }
                Cipher cipher = initCipherMINI(Cipher.DECRYPT_MODE);
                String str = value.replaceAll("-", "+").replaceAll("_", "/");
                byte[] buffer = new BASE64Decoder().decodeBuffer(str);
                byte[] bytes = cipher.doFinal(buffer);
                return new String(bytes, "UTF-8").trim();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

	private static Cipher initCipherMINI(int mode) throws NoSuchAlgorithmException,
			NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
		Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
		SecretKeySpec secretKeySpec = new SecretKeySpec(miniKey.getBytes(), "AES");
		IvParameterSpec ivParameterSpec = new IvParameterSpec(miniIv.getBytes());
		cipher.init(mode, secretKeySpec, ivParameterSpec);
		return cipher;
	}

    /**
     * 解密
     *
     * @return
     * @throws Exception
     */
    public static String desEncryptForTermianl(String data) throws Exception {
        if (StringUtils.isNotEmpty(data) && !"null".equals(data)) {
            //data = URLDecoder.decode(data,"UTF-8");
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(terminalKey.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(terminalIv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "UTF-8");
            return originalString.trim();
        } else {
            return null;
        }

    }


    /**
     * 加密
     *
     * @return
     * @throws Exception
     */
    public static String encryptForTermianl(String data) throws Exception {
        if (StringUtils.isNotEmpty(data)) {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes("UTF-8");
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(terminalKey.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(terminalIv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new BASE64Encoder().encode(encrypted);
        } else {
            return null;
        }
    }

	private static byte[] getBytes(Cipher cipher, String value) throws IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
		int blockSize = cipher.getBlockSize();
		byte[] dataBytes = value.getBytes("UTF-8");
		int plaintextLength = dataBytes.length;
		if (plaintextLength % blockSize != 0) {
			plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
		}
		byte[] plaintext = new byte[plaintextLength];
		System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
		return cipher.doFinal(plaintext);
	}

    /**
     * 加密  转换后不含特殊字符
     *
     * @param value
     * @return
     */
    public static String encryptYx(String value) {
        if (StringUtils.isNotEmpty(value)) {
            try {
                Cipher cipher = initCipherYx(Cipher.ENCRYPT_MODE);
                byte[] bytes = getBytes(cipher, value);
                String encode = new BASE64Encoder().encode(bytes);
                String str = encode.replaceAll("\\+", "-").replaceAll("/", "_");
                return str.replaceAll("\\r|\\n", "").replaceAll("=", "");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

    /**
     * 解密
     *
     * @param value
     * @return
     */
    public static String decryptYx(String value) {
        if (StringUtils.isNotEmpty(value)) {
            try {
                while ((value.length()) % 4 != 0) {
                    value += "=";
                }
                Cipher cipher = initCipherYx(Cipher.DECRYPT_MODE);
                String str = value.replaceAll("-", "+").replaceAll("_", "/");
                byte[] buffer = new BASE64Decoder().decodeBuffer(str);
                byte[] bytes = cipher.doFinal(buffer);
                return new String(bytes, "UTF-8").trim();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

    private static Cipher initCipherYx(int mode) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyYx.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivYx.getBytes());
        cipher.init(mode, secretKeySpec, ivParameterSpec);
        return cipher;
    }

    /**
     * 加密  转换后不含特殊字符
     *
     * @param value
     * @return
     */
    public static String encryptTml(String value) {
        if (!StringUtils.isEmpty(value)) {
            try {
                Cipher cipher = initCipherTml(Cipher.ENCRYPT_MODE);
                byte[] bytes = getBytes(cipher, value);
                String encode = new BASE64Encoder().encode(bytes);
//                String str = encode.replaceAll("\\+", "-").replaceAll("/", "_");
//                return str.replaceAll("\\r|\\n", "").replaceAll("=", "");
                return encode.replaceAll("\\r|\\n", "");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

    /**
     * 解密
     *
     * @param value
     * @return
     */
    public static String desCryptTml(String value) {
        if (!StringUtils.isEmpty(value)) {
            try {
                while ((value.length()) % 4 != 0) {
                    value += "=";
                }
                Cipher cipher = initCipherTml(Cipher.DECRYPT_MODE);
                String str = value.replaceAll("-", "+").replaceAll("_", "/");
                byte[] buffer = new BASE64Decoder().decodeBuffer(str);
                byte[] bytes = cipher.doFinal(buffer);
                return new String(bytes, StandardCharsets.UTF_8).trim();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return "";
    }

    private static Cipher initCipherTml(int mode) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        SecretKeySpec secretKeySpec = new SecretKeySpec(tmlKey.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(tmlIv.getBytes());
        cipher.init(mode, secretKeySpec, ivParameterSpec);
        return cipher;
    }

    public static String encryptForAnnualBill(String data) throws Exception {
        if (StringUtils.isNotEmpty(data)) {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes("UTF-8");
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(annualEbillKey.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(annualEbillIv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new BASE64Encoder().encode(encrypted).replace("+", "@").replace("/", "$").replace("=", "*");
        } else {
            return null;
        }
    }

    public static String desEncryptForAnnualBill(String data) throws Exception {
        data = data.replace("@", "+").replace("$", "/").replace("*", "=");
        if (StringUtils.isNotEmpty(data) && !"null".equals(data)) {
            //data = URLDecoder.decode(data,"UTF-8");
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(annualEbillKey.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(annualEbillIv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "UTF-8");
            return originalString.trim();
        } else {
            return null;
        }

    }

    public static void main(String[] args) throws Exception {
        System.out.println(AesUtils.desEncrypt("6LFn568MFKp2uPQkvxM38w=="));
        System.out.println(AesUtils.encryptForTemplate("0111374285"));
        System.out.println("6LFn568MFKp2uPQkvxM38w==");
    }

}
